package org.mtmi.ui.controls.midi;

import java.util.Collection;
import java.util.Iterator;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.mtmi.midi.MidiManager;
import org.mtmi.ui.IMG;
import org.mtmi.ui.M;
import org.mtmi.ui.controls.listeners.PopupListener;
import org.mtmi.ui.controls.midi.popups.ChooseMidiOutputPopup;
import org.mtmi.ui.controls.popups.AbstractButtonPopup;
import org.mtmi.ui.drawables.IDrawable;
import org.mtmi.ui.scenes.COLOR;
import org.mtmi.ui.scenes.FontManager;
import org.mtmi.ui.scenes.SceneManager;

import rwmidi.MidiOutput;

/**
 * This action display a popup to choose a midi port list,
 * and change the MIDI port of IMidiControl (or collection of).
 */
public class ChangeMidiOutputAction extends AbstractRetargettableMidiAction
{
	
	public ChangeMidiOutputAction( IMidiControl c ) {
		super( c );
	}
	
	/** @return target output, or -1 if output is a bad or a collection which not share output */
	private int getOutput() {
		if( target instanceof IMidiControl ) {
			return ((IMidiControl)target).getMidiOutput();
		} else {
			//check if all control have same midi output:
			Collection<?> c = (Collection<?>)target;
			int output=-1;
			boolean f=true;
			for( Iterator<?> I = c.iterator(); I.hasNext(); ) {
				int o = ((IMidiControl)I.next()).getMidiOutput();
				if( f ) {
					output = o; f=false;
				} else {
					if( o!=output ) {
						//output is not shared by list elements
						return -1;
					}
				}
			}
			return output;
		}
	}
	
	@Override
	public IDrawable getImage() {
		int output = getOutput();
		if( output < 0 ) {
			return IMG.GetD( IMG.I_MIDI_PORT );
		} else {
			//can display MIDI output number:
			return new PortImage( output );
		} 
	}

	private ChooseMidiOutputPopup popup;
	
	@Override
	public void run() {
		if( popup==null || popup.isDisposed() ) {
			int output = getOutput();
			popup = new ChooseMidiOutputPopup( SceneManager.getDefault().getScene(), M.SCENE_EDITOR_CONTROL );
			if( output>=0 ) {
				popup.setMidiOutput( MidiManager.getInstance().getMidiOutput( output ) );
			}
			popup.addResponseListener( new PopupListener() {
				@Override
				public void popupButtonSelected(int id) {
					if( id == AbstractButtonPopup.OK ) {
						if( target instanceof IMidiControl ) {
							run( (IMidiControl)target, popup.getMidiOutput() );
						} else {
							for( Object o : (Collection<?>)target ) {
								run( (IMidiControl)o, popup.getMidiOutput() );
							}
						}
					}
				}
			});
		} else {
			popup.dispose();
		}
	}
	
	protected void run( IMidiControl c, MidiOutput output ) {
		c.setMidiOutput( MidiManager.getInstance().getIndexOf( output ) );
	}

	//note: essai d'image de channel avec la valeur inscrite dedans
	private static class PortImage implements IDrawable
	{
		int output;
		private IDrawable img;
		
		PortImage( int p ) { 
			output=p;
			img = IMG.GetD( IMG.I_MIDI_PORT );
		}
		@Override
		public Point computeSize(int width, int height) {
			Point sz = img.computeSize( width, height );
			GC gc = SceneManager.getDefault().getScene().getGC();
			gc.setFont( FontManager.getInstance().getToolBarFont() );
			Point st = gc.textExtent( Integer.toString(output) );
			sz.x += 5+st.x;
			sz.y = Math.max( sz.y, st.y );
			return sz;
		}

		@Override
		public void paint( GC gc, int x, int y, int width, int height, int state ) {
			
			gc.setFont( FontManager.getInstance().getToolBarFont() );
			String txt = Integer.toString(output);
			Point st = gc.textExtent( txt );
			
			int xt = x+width-st.x;
			int yt = y+(height-st.y)/2;
			
			gc.setForeground( COLOR.grey0 );
			gc.drawText( txt, xt, yt, true );
			
			img.paint( gc, x, y, width-5-st.x, height, state );
		}
		
	}
}